﻿#pragma once

#include "Misc/EnumClassFlags.h"
#include "Config.generated.h"

class UClass;
class UFunction;
class UProperty;


enum class EPropertyAccessorAvailability : uint8
{
	None			= 0,
	Default			= 1 << 0,	// Getter, Setter
	AltAccessor		= 1 << 1,	// $Getter, $Setter
	StructRefArray	= 1 << 2	// $getStructRefArray_(PropName)
};
ENUM_CLASS_FLAGS(EPropertyAccessorAvailability);


UCLASS(config = Engine, defaultconfig)
class V8_API UV8Config : public UObject
{
	GENERATED_BODY()

public:
	static const UV8Config& Get()
	{
		static UV8Config* CDO = UV8Config::StaticClass()->GetDefaultObject<UV8Config>();
		return *CDO;
	}

	FString Safeify(const FString& Name) const;

	bool CanExportClass(const UClass* Class) const;
	bool CanExportFunction(const UClass* Class, const UFunction* Function) const;
	bool CanExportProperty(const UStruct* Class, const UProperty* Property) const;

	bool IsWriteDisabledProperty(UProperty* Property) const { return false; }
	EPropertyAccessorAvailability GetPropertyAccessorAvailability(UProperty* Property) const;

	FString GetAlias(UFunction* Function, bool no_empty = false) const;

	bool FlushInspectorWebSocketOnWritable() const { return true; }

public:
	/**
	 * If true, alternative property accessors, those start with dollar sign($), will be added for
	 * every properties in generated classes or structs whose are generated by calling
	 * CreateClass or CreateStruct like doing in 'uclass.js'.
	 * But, for FText or Array<AnyStruct> properties, alt.accessors will be added regardless of this setting.
	 * About implementation of alternative property accessors, refer to Internal(Read|Write)Property function
	 * especially codes handling '(FPropertyAccessorFlags)Flags.Alternative' flag
	 * in FJavascriptIsolateImplementation class.
	 */
	UPROPERTY(config)
	bool bGenAltPropAccessorForAllProp = true;

	/**
	 * If true, $getStructRefArray_(PropName) function will be generated for array properties
	 * which is containing struct instances. This function does the same thing with
	 * the alternative property getter for that property.
	 * Only used to explicit difference from the default property accessor.
	 */
	UPROPERTY(config)
	bool bGenGetStructRefArrayFunction = false;
};

// For backward compatility
struct FV8Config
{
	static FString Safeify(const FString& Name)													{ return UV8Config::Get().Safeify(Name); }

	static bool CanExportClass(const UClass* Class)												{ return UV8Config::Get().CanExportClass(Class); }
	static bool CanExportFunction(const UClass* Class, const UFunction* Function)				{ return UV8Config::Get().CanExportFunction(Class, Function); }
	static bool CanExportProperty(const UStruct* Class, const UProperty* Property)				{ return UV8Config::Get().CanExportProperty(Class, Property); }

	static bool IsWriteDisabledProperty(UProperty* Property)									{ return UV8Config::Get().IsWriteDisabledProperty(Property); }
	static EPropertyAccessorAvailability GetPropertyAccessorAvailability(UProperty* Property)	{ return UV8Config::Get().GetPropertyAccessorAvailability(Property); }

	static FString GetAlias(UFunction* Function, bool no_empty = false)							{ return UV8Config::Get().GetAlias(Function, no_empty); }

	static bool FlushInspectorWebSocketOnWritable()												{ return UV8Config::Get().FlushInspectorWebSocketOnWritable(); }
};

